package com.freeter.common;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.symmetric.DES;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;

import static javax.crypto.Cipher.ENCRYPT_MODE;

public class DesHelper {

    // 算法名称
    public static final String KEY_ALGORITHM = "DES";
    // 算法名称/加密模式/填充方式
    public static final String CIPHER_ALGORITHM_ECB = "DES/ECB/PKCS5Padding";
    public static final String CIPHER_ALGORITHM_CBC = "DES/CBC/PKCS5Padding";



    /**
     * 加密
     * @param datasource byte[]
     * @return byte[]
     */
    public static byte[] encrypt(byte[] datasource) {
        try{

            //https://blog.csdn.net/jjwwmlp456/article/details/20933021

            /*
             * 使用CBC mode
             * 使用密钥工厂生成密钥，加密 解密
             * iv: DES in CBC mode and RSA ciphers with OAEP encoding operation.
             */
            DESKeySpec dks = new DESKeySpec("d7%&G$X*".getBytes("UTF-8"));
            //创建一个密匙工厂，然后用它把DESKeySpec转换成
            SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
            SecretKey secretKey = factory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
            //盐值，密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec("x^%U(*_^".getBytes("UTF-8")));
            //Cipher对象实际完成加密操作
            return  cipher.doFinal(datasource); //加密


        }catch(Throwable e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 加密
     * @param datasource byte[]
     * @return byte[]
     */
    public static byte[] Decrypt(byte[] datasource) {
        try{

            //https://blog.csdn.net/jjwwmlp456/article/details/20933021

            /*
             * 使用CBC mode
             * 使用密钥工厂生成密钥，加密 解密
             * iv: DES in CBC mode and RSA ciphers with OAEP encoding operation.
             */
            DESKeySpec dks = new DESKeySpec("d7%&G$X*".getBytes("UTF-8"));
            //创建一个密匙工厂，然后用它把DESKeySpec转换成
            SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
            SecretKey secretKey = factory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
            //盐值，密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec("x^%U(*_^".getBytes("UTF-8")));
            //Cipher对象实际完成加密操作
            return  cipher.doFinal(datasource); //加密


        }catch(Throwable e){
            e.printStackTrace();
        }
        return null;
    }

    public static String hex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte aByte : bytes) {
            result.append(String.format("%02X", aByte));
            // upper case
            // result.append(String.format("%02X", aByte));
        }
        return result.toString();
    }

    /**
     * hex转byte数组
     * @param hex
     * @return
     */
    public static byte[] hexToByte(String hex){
        int m = 0, n = 0;
        int byteLen = hex.length() / 2; // 每两个字符描述一个字节
        byte[] ret = new byte[byteLen];
        for (int i = 0; i < byteLen; i++) {
            m = i * 2 + 1;
            n = m + 1;
            int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
            ret[i] = Byte.valueOf((byte)intVal);
        }
        return ret;
    }

    /**
     * byte数组转hex
     * @param bytes
     * @return
     */
    public static String byteToHex(byte[] bytes){
        String strHex = "";
        StringBuilder sb = new StringBuilder("");
        for (int n = 0; n < bytes.length; n++) {
            strHex = Integer.toHexString(bytes[n] & 0xFF);
            sb.append((strHex.length() == 1) ? "0" + strHex : strHex); // 每个字节由两个字符表示，位数不够，高位补0
        }
        return sb.toString().trim();
    }

    public static void main(String[] args) throws Exception {
        byte[] encryptStr = encrypt("e01eea55-855c-4100-a336-cede6a0619db__yilf__637629674174171612".getBytes("UTF-8"));
        System.out.println(hex(encryptStr));

        byte[] decryptStr = Decrypt(hexToByte(hex(encryptStr)));
        System.out.println(new String(decryptStr));

    }


    private String key;

    private String iv;

}
